<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>何为爱情</title>
        <style>        
        #love{
            margin:67px auto;
           text-align:center;
            font-size:2em;
            width:97%;
            height:340px;      
            background: url(backg.jpg) no-repeat 50% 50%;
        }     
        
        html, body {
            color:white;            
            margin:0;width:100%;padding:0;
            width: 100%;
            min-width: 1000px;
            height: 100%;
            min-height: 400px;
            overflow: hidden;
        }


        .container {
            position: relative;
            height: 100%;
        }

 
        #mask {
            position: absolute;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, .8);
            z-index: 900;
        }
        /* ???? */
        
        #sky {
            width: 100%;
            height: 100%;
            background: linear-gradient(rgba(0, 150, 255, 1), rgba(0, 150, 255, .8), rgba(0, 150, 255, .5));
        }
        /* ?? */
        
        #moon {
            position: absolute;
            top: 50px;
            right: 200px;
            width: 120px;
            height: 120px;
            background: rgba(251, 255, 25, 0.938);
            border-radius: 50%;
            box-shadow: 0 0 20px rgba(251, 255, 25, 0.5);
            z-index: 9999;
        }
        /* ???? */
        
        .blink {
            position: absolute;
            background: rgb(255, 255, 255);
            border-radius: 50%;
            box-shadow: 0 0 5px rgb(255, 255, 255);
            opacity: 0;
            z-index: 10000;
        }
        /* ?? */
        
        .star {
            position: absolute;
            opacity: 0;
            z-index: 10000;
        }
        
        .star::after {
            content: "";
            display: block;
            border: solid;
            border-width: 2px 0 2px 80px;
            /*?????????*/
            border-color: transparent transparent transparent rgba(255, 255, 255, 1);
            border-radius: 2px 0 0 2px;
            transform: rotate(-45deg);
            transform-origin: 0 0 0;
            box-shadow: 0 0 20px rgba(255, 255, 255, .3);
        }
        /* ? */
        
        .cloud {
            position: absolute;
            width: 100%;
            height: 100px;
        }
        
        .cloud-1 {
            bottom: -100px;
            z-index: 1000;
            opacity: 1;
            transform: scale(1.5);
            -webkit-transform: scale(1.5);
            -moz-transform: scale(1.5);
            -ms-transform: scale(1.5);
            -o-transform: scale(1.5);
        }
        
        .cloud-2 {
            left: -100px;
            bottom: -50px;
            z-index: 999;
            opacity: .5;
            transform: rotate(7deg);
            -webkit-transform: rotate(7deg);
            -moz-transform: rotate(7deg);
            -ms-transform: rotate(7deg);
            -o-transform: rotate(7deg);
        }
        
        .cloud-3 {
            left: 120px;
            bottom: -50px;
            z-index: 999;
            opacity: .1;
            transform: rotate(-10deg);
            -webkit-transform: rotate(-10deg);
            -moz-transform: rotate(-10deg);
            -ms-transform: rotate(-10deg);
            -o-transform: rotate(-10deg);
        }
        
        .circle {
            position: absolute;
            border-radius: 50%;
            background: #fff;
        }
        
        .circle-1 {
            width: 100px;
            height: 100px;
            top: -50px;
            left: 10px;
        }
        
        .circle-2 {
            width: 150px;
            height: 150px;
            top: -50px;
            left: 30px;
        }
        
        .circle-3 {
            width: 300px;
            height: 300px;
            top: -100px;
            left: 80px;
        }
        
        .circle-4 {
            width: 200px;
            height: 200px;
            top: -60px;
            left: 300px;
        }
        
        .circle-5 {
            width: 80px;
            height: 80px;
            top: -30px;
            left: 450px;
        }
        
        .circle-6 {
            width: 200px;
            height: 200px;
            top: -50px;
            left: 500px;
        }
        
        .circle-7 {
            width: 100px;
            height: 100px;
            top: -10px;
            left: 650px;
        }
        
        .circle-8 {
            width: 50px;
            height: 50px;
            top: 30px;
            left: 730px;
        }
        
        .circle-9 {
            width: 100px;
            height: 100px;
            top: 30px;
            left: 750px;
        }
        
        .circle-10 {
            width: 150px;
            height: 150px;
            top: 10px;
            left: 800px;
        }
        
        .circle-11 {
            width: 150px;
            height: 150px;
            top: -30px;
            left: 850px;
        }
        
        .circle-12 {
            width: 250px;
            height: 250px;
            top: -50px;
            left: 900px;
        }
        
        .circle-13 {
            width: 200px;
            height: 200px;
            top: -40px;
            left: 1000px;
        }
        
        .circle-14 {
            width: 300px;
            height: 300px;
            top: -70px;
            left: 1100px;
        }
        </style>
    </head>
    <body>
            
        <div class="container">
                <div id="mask">
                   
                    <div id="love">
                            <div id="say">
                                   <p>相濡以沫</p>
                                   <p>不如相忘于江湖</p>
                            </div>
                    </div>
                </div>
                <div id="sky"></div>
                 <div id="moon"></div>
                
                <div id="stars"></div>
                
                <div class="cloud cloud-1"></div>
                <div class="cloud cloud-2"></div>
                <div class="cloud cloud-3"></div>

                
        </div>
        
            <script>
                function requestAnimation(obj) {
    //—————————————————————————————————————????—————————————————————————————————————————————
    //????
    const parameter = {
        ele: null,
        attr: null,
        value: null,
        time: 1000,
        tween: "linear",
        flag: true,
        stop: false,
        fn: ""
    }

    //??????
    Object.assign(parameter, obj); //??????

    //—————————————————————————————————————????—————————————————————————————————————————————
    //??????????,????
    let start = 0; //?????????
    let target = (typeof parameter.ele === "string" ? document.querySelector(parameter.ele) : parameter.ele), //????
        attr = parameter.attr, //????
        beginAttr = parseFloat(getComputedStyle(target)[attr]), //attr???
        value = parameter.value, //?????
        count = value - beginAttr, //?????
        time = parameter.time, //??????,
        tween = parameter.tween, //????
        flag = parameter.flag,
        callback = parameter.fn, //????
        curVal = 0; //?????

    //????????????????
    (function() {
        if (attr instanceof Array) {
            beginAttr = [];
            count = [];
            for (let i of attr) {
                const val = parseFloat(getComputedStyle(target)[i]);
                beginAttr.push(val);
                count.push(value - val);
            }
        }
        if (value instanceof Array) {
            for (let i in value) {
                count[i] = value[i] - beginAttr[i];
            }
        }
    })();

    //????
    function animate(timestamp) {
        if (parameter.stop) return; //??
        //???????
        if (!start) start = timestamp;
        //?????
        let t = timestamp - start;
        //??????
        if (beginAttr instanceof Array) {
            // const len = beginAttr.length //????????

            //?????1?——???????????/????
            if (typeof count === "number") { //???
                //???
                if (typeof time === "number") {
                    if (t > time) t = time; //?????????

                    //??attr?????
                    for (let i in beginAttr) {
                        if (flag) curVal = Tween[tween](t, beginAttr[i], count, time); //??Tween????????,??????????????
                        else curVal = Tween[tween](t, beginAttr[i], count + beginAttr[i], time); //??Tween???????????????????????
                        if (attr[i] === "opacity") target.style[attr[i]] = curVal; //?????
                        else target.style[attr[i]] = curVal + "px"; //?????

                        if (t < time) requestAnimationFrame(animate); //???????
                        else callback && callback(); //??????
                    }
                    return;
                }

                //????
                if (time instanceof Array) {
                    //??time?attr?????
                    for (let i in beginAttr) {
                        //????
                        if (!time[i] && time[i] !== 0) {
                            throw new Error(
                                "The input time's length is not equal to attribute's length");
                        }

                        //????????????????????
                        if (parseFloat(getComputedStyle(target)[attr[i]]) === (typeof value === "number" ? value : value[i]))
                            continue;
                        // t = timestamp - start; //???????t
                        if (t > time[i]) t = time[i]; //?????????

                        if (flag || attr[i] === "opacity") curVal = Tween[tween](t, beginAttr[i], count, i); //??Tween????????,??????????????
                        else curVal = Tween[tween](t, beginAttr[i], count + beginAttr[i], i); //??Tween???????????????????????
                        if (attr[i] === "opacity") target.style[attr[i]] = curVal; //?????
                        else target.style[attr[i]] = curVal + "px"; //?????
                    }

                    if (t < Math.max(...time)) requestAnimationFrame(animate); //?????????
                    else callback && callback(); //??????????????????????
                    return;
                }
            }

            //?????2?——????????????/????
            if (count instanceof Array) {
                //???
                if (typeof time === "number") {

                    if (t > time) t = time; //?????????

                    for (let i in beginAttr) { //??attr?count?????
                        //????
                        if (!count[i] && count[i] !== 0) {
                            throw new Error(
                                "The input value's length is not equal to attribute's length");
                        }

                        if (flag || attr[i] === "opacity") curVal = Tween[tween](t, beginAttr[i], count[i], time); //??Tween????????,??????????????
                        else curVal = Tween[tween](t, beginAttr[i], count[i] + beginAttr[i], time); //??Tween???????????????????????
                        if (attr[i] === "opacity") target.style[attr[i]] = curVal; //?????
                        else target.style[attr[i]] = curVal + "px"; //?????
                    }

                    if (t < time) requestAnimationFrame(animate); //?????????
                    else callback && callback(); //??????????????????????
                    return;
                }

                //????
                if (time instanceof Array) {
                    for (let i in beginAttr) {
                        //????
                        if (!time[i] && time[i] !== 0) {
                            throw new Error(
                                "The input time's length is not equal to attribute's length");
                        }

                        //????????????????????
                        if (parseFloat(getComputedStyle(target)[attr[i]]) === (typeof value === "number" ? value : value[i]))
                            continue;

                        if (t > time[i]) t = time[i]; //?????????

                        //????
                        if (!count[i] && count[i] !== 0) {
                            throw new Error(
                                "The input value's length is not equal to attribute's length");
                        }

                        if (flag || attr[i] === "opacity") curVal = Tween[tween](t, beginAttr[i], count[i], time[i]); //??Tween????????,??????????????
                        else curVal = Tween[tween](t, beginAttr[i], count[i] + beginAttr[i], time[i]); //??Tween???????????????????????
                        if (attr[i] === "opacity") target.style[attr[i]] = curVal;
                        else target.style[attr[i]] = curVal + "px";
                    }

                    if (t < Math.max(...time)) requestAnimationFrame(animate);
                    else callback && callback();
                    return;
                }
            }

        }

        //?????
        if (t > time) t = time;
        if (flag || attr === "opacity") curVal = Tween[tween](t, beginAttr, count, time); //??Tween????????,??????????????
        else curVal = Tween[tween](t, beginAttr[i], count + beginAttr, time); //??Tween???????????????????????
        if (attr === "opacity") target.style[attr] = curVal;
        else target.style[attr] = curVal + "px";

        if (t < time) requestAnimationFrame(animate);
        else callback && callback();

    }

    requestAnimationFrame(animate);
    return parameter; //?????????????
}
//Tween.js
/*
 * t : time ????
 * b : begin ???
 * c : count ?????
 * d : duration ????
 *
 * ????
 *
 * http://www.cnblogs.com/bluedream2009/archive/2010/06/19/1760909.html
 * */

let Tween = {
    linear: function(t, b, c, d) { //??
        return c * t / d + b;
    },
    easeIn: function(t, b, c, d) { //????
        return c * (t /= d) * t + b;
    },
    easeOut: function(t, b, c, d) { //????
        return -c * (t /= d) * (t - 2) + b;
    },
    easeBoth: function(t, b, c, d) { //??????
        if ((t /= d / 2) < 1) {
            return c / 2 * t * t + b;
        }
        return -c / 2 * ((--t) * (t - 2) - 1) + b;
    },
    easeInStrong: function(t, b, c, d) { //?????
        return c * (t /= d) * t * t * t + b;
    },
    easeOutStrong: function(t, b, c, d) { //?????
        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
    },
    easeBothStrong: function(t, b, c, d) { //????????
        if ((t /= d / 2) < 1) {
            return c / 2 * t * t * t * t + b;
        }
        return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
    },
    elasticIn: function(t, b, c, d, a, p) { //????????????
        if (t === 0) {
            return b;
        }
        if ((t /= d) == 1) {
            return b + c;
        }
        if (!p) {
            p = d * 0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    },
    elasticOut: function(t, b, c, d, a, p) { //????????????
        if (t === 0) {
            return b;
        }
        if ((t /= d) == 1) {
            return b + c;
        }
        if (!p) {
            p = d * 0.3;
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
    },
    elasticBoth: function(t, b, c, d, a, p) {
        if (t === 0) {
            return b;
        }
        if ((t /= d / 2) == 2) {
            return b + c;
        }
        if (!p) {
            p = d * (0.3 * 1.5);
        }
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else {
            var s = p / (2 * Math.PI) * Math.asin(c / a);
        }
        if (t < 1) {
            return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) *
                Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        }
        return a * Math.pow(2, -10 * (t -= 1)) *
            Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
    },
    backIn: function(t, b, c, d, s) { //??????????
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        return c * (t /= d) * t * ((s + 1) * t - s) + b;
    },
    backOut: function(t, b, c, d, s) {
        if (typeof s == 'undefined') {
            s = 3.70158; //?????
        }
        return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
    },
    backBoth: function(t, b, c, d, s) {
        if (typeof s == 'undefined') {
            s = 1.70158;
        }
        if ((t /= d / 2) < 1) {
            return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
        }
        return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
    },
    bounceIn: function(t, b, c, d) { //??????????
        return c - Tween['bounceOut'](d - t, 0, c, d) + b;
    },
    bounceOut: function(t, b, c, d) {
        if ((t /= d) < (1 / 2.75)) {
            return c * (7.5625 * t * t) + b;
        } else if (t < (2 / 2.75)) {
            return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
        } else if (t < (2.5 / 2.75)) {
            return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
        }
        return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
    },
    bounceBoth: function(t, b, c, d) {
        if (t < d / 2) {
            return Tween['bounceIn'](t * 2, 0, c, d) * 0.5 + b;
        }
        return Tween['bounceOut'](t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
    }
}


//———————————————————————————————————————————DOM??———————————————————————————————————————————————————
// ????
// ele: ???????????id??class????????????????????
// node: ????????????
// n: ??????
// className: ?????class???????????class??????
// boolean: ????????????????????????false?????????????
function addChild(ele, node, n, className, boolean) {
    //????
    let parent = null;

    if (typeof ele !== "string") parent = ele;
    else if (ele[0] === "#") parent = document.getElementById(ele.slice(1));
    else if (ele[0] === ".") {
        if (boolean === false) parent = document.getElementsByClassName(ele.slice(1))[0];
        else parent = document.getElementsByClassName(ele.slice(1));
    } else {
        if (boolean === false) parent = docuemnt.getElementsByTagName(ele)[0];
        else parent = document.getElementsByTagNameNS(ele);
    }

    //???????????????? 
    const obj = {
        "parent": parent,
        "children": []
    };

    //????
    if (boolean) {
        for (let i = 0; i < parent.length; i++) {
            //??????
            const fragment = document.createDocumentFragment();
            //???????????
            obj.children[i] = [];

            for (let j = 0; j < n; j++) {
                const target = document.createElement(node);
                target.className = className;
                fragment.appendChild(target);
                //??????????????
                obj.children[i][j] = target;
            }

            parent[i].appendChild(fragment)
        }
    } else {
        //??????
        const fragment = document.createDocumentFragment();

        for (let i = 0; i < n; i++) {
            const target = document.createElement(node);
            target.className = className;
            fragment.appendChild(target);
            //???????????
            obj.children[i] = target;
        }
        //??????????????
        parent.appendChild(fragment);
    }

    //????????????
    return obj;
}




            //????
setInterval(function() {
    const obj = addChild("#sky", "div", 2, "star");

    for (let i = 0; i < obj.children.length; i++) {
        const top = -50 + Math.random() * 200 + "px",
            left = 200 + Math.random() * 1200 + "px",
            scale = 0.3 + Math.random() * 0.5;
        const timer = 1000 + Math.random() * 1000;

        obj.children[i].style.top = top;
        obj.children[i].style.left = left;
        obj.children[i].style.transform = `scale(${scale})`;

        requestAnimation({
            ele: obj.children[i],
            attr: ["top", "left", "opacity"],
            value: [150, -150, .8],
            time: timer,
            flag: false,
            fn: function() {
                requestAnimation({
                    ele: obj.children[i],
                    attr: ["top", "left", "opacity"],
                    value: [150, -150, 0],
                    time: timer,
                    flag: false,
                    fn: () => {
                        obj.parent.removeChild(obj.children[i]);
                    }
                })
            }
        });
    }

}, 1000);

//??????
setInterval(function() {
    const obj = addChild("#stars", "div", 2, "blink");

    for (let i = 0; i < obj.children.length; i++) {
        const top = -50 + Math.random() * 500 + "px",
            left = 200 + Math.random() * 1200 + "px",
            round = 1 + Math.random() * 2 + "px";
        const timer = 1000 + Math.random() * 4000;

        obj.children[i].style.top = top;
        obj.children[i].style.left = left;
        obj.children[i].style.width = round;
        obj.children[i].style.height = round;

        requestAnimation({
            ele: obj.children[i],
            attr: "opacity",
            value: .5,
            time: timer,
            flag: false,
            fn: function() {
                requestAnimation({
                    ele: obj.children[i],
                    attr: "opacity",
                    value: 0,
                    time: timer,
                    flag: false,
                    fn: function() {
                        obj.parent.removeChild(obj.children[i]);
                    }
                });
            }
        });
    }

}, 1000);

//????
requestAnimation({
    ele: "#moon",
    attr: "right",
    value: 1200,
    time: 10000000,
});


// ???
const clouds = addChild(".cloud", "div", 14, "circle", true);
for (let i = 0; i < clouds.children.length; i++) {
    for (let j = 0; j < clouds.children[i].length;) {
        clouds.children[i][j].classList.add(`circle-${++j}`);
    }
}
//???

let flag = 1;
setInterval(
    function() {
        const clouds = document.querySelectorAll(".cloud");
        const left = Math.random() * 5;
        bottom = Math.random() * 5;

        let timer = 0;
        for (let i = 0; i < clouds.length; i++) {
            requestAnimation({
                ele: clouds[i],
                attr: ["left", "bottom"],
                value: flag % 2 ? [-left, -bottom] : [left, bottom],
                time: timer += 500,
                flag: false,
                fn: function() {
                    requestAnimation({
                        ele: clouds[i],
                        attr: ["left", "bottom"],
                        value: flag % 2 ? [left, bottom] : [-left, -bottom],
                        time: timer,
                        flag: false
                    })
                }
            });
        }

        flag++;
    }, 2000)








    
            
            </script>
    </body>
</html>
